import axios from "axios";
import constant from "./constant";
//处理url参数
import qs from "qs";

import store from "../store";


axios.defaults.baseURL = constant.baseURL;
//  添加请求拦截器
axios.interceptors.request.use(function (config) {
  return config;  // 在发送请求之前做些什么
}, function (error) {
  return Promise.reject(error);  // 对请求错误做些什么
});

// 添加响应拦截器
axios.interceptors.response.use(function (response) {
  // 检查相应数据是否包含空响应或非成功状态的响应
  if (response.data !== null && response.data.hasOwnProperty("code") && response.data.code !== 200) {
    if (response.data.code === 300) {
      store.commit("loadCurrentUser", {});   // 如果是300，表示用户需要重新登录
      localStorage.removeItem("userToken");  // 本地存储中清除用户token
      store.commit("loadCurrentAdmin", {}); 
      localStorage.removeItem("adminToken"); // 本地存储中清除管理员token
      window.location.href = constant.webURL + "/user";  // 将页面重定向到登录页面
    }
    // 如果响应数据中的code属性不等于300，代码会抛出一个错误，并将响应数据中的message属性作为错误信息
    return Promise.reject(new Error(response.data.message));
  } else {
    return response;  // 如果是成功状态，则返回响应数据
  }
}, function (error) {  // 如果是响应错误
  return Promise.reject(error);  // 对响应错误进行处理，并返回一个被拒绝的Promise
});

// 当data为URLSearchParams对象时设置为application/x-www-form-urlencoded;charset=utf-8
// 当data为普通对象时，会被设置为application/json;charset=utf-8


export default {
  /**
  * @author DavidLee 
  * @title post 
  * @date 2024-10-14
  * @description 发送HTTP POST请求。该函数使用了axios库来处理HTTP请求，并支持传递不同的参数和配置
  * @param  url：请求的URL地址
  * @param  params：请求的参数，默认为空对象
  * @param  isAdmin：是否为管理员请求，默认为false
  * @param  json：是否为JSON格式，默认为true
  * @return Promise：返回一个Promise对象，该对象在请求成功时解析为响应数据，在请求失败时拒绝为错误信息
  */
  post(url, params = {}, isAdmin = false, json = true) {
    let config;
    if (isAdmin) {   // 如果是管理员
      config = {
        headers: {"Authorization": localStorage.getItem("adminToken")}  // 设置请求头中的Authorization字段为管理员token
      };
    } else {
      config = {
        headers: {"Authorization": localStorage.getItem("userToken")}  // 否则，设置请求头中的Authorization字段为用户token
      };
    }

    return new Promise((resolve, reject) => {  // 使用Promise对象来处理POST请求，以便在请求成功或失败时调用相应的回调函数
      axios
        .post(url, json ? params : qs.stringify(params), config) // 使用axios.post方法发送POST请求，根据json参数的值决定是否将参数序列化为JSON格式
        .then(res => {
          resolve(res.data); // 在请求成功时，将响应数据传递给resolve函数
        })
        .catch(err => {
          reject(err);       // 在请求失败时，将错误信息传递给reject函数
        });
    });
  },

  /**
  * @author DavidLee 
  * @title get 
  * @date 2024-10-14
  * @description 发送HTTP GET请求。该函数使用了axios库来处理请求
  * @param  url：请求的URL地址
  * @param  params：请求的参数，默认为空对象
  * @param  isAdmin：是否为管理员请求，默认为false
  * @return Promise：返回一个Promise对象，该对象在请求成功时解析为响应数据，在请求失败时拒绝为错误信息
  */
  get(url, params = {}, isAdmin = false) {
    let headers;
    if (isAdmin) {
      headers = {"Authorization": localStorage.getItem("adminToken")};  // 同上
    } else {
      headers = {"Authorization": localStorage.getItem("userToken")};
    }

    return new Promise((resolve, reject) => {
      axios.get(url, {    // 使用axios.get方法发送GET请求，传递URL、查询参数和请求头
        params: params,
        headers: headers
      }).then(res => {    // 在请求成功时，将响应数据传递给resolve函数
        resolve(res.data);
      }).catch(err => {   // 在请求失败时，将错误信息传递给reject函数
        reject(err)
      })
    });
  },

  /**
  * @author DavidLee 
  * @title upload 
  * @date 2024-10-14
  * @description 上传文件或数据到指定的URL。该函数使用了axios库来发送HTTP请求
  * @param  url：请求的URL地址
  * @param  params：请求的参数，默认为空对象
  * @param  isAdmin：是否为管理员请求，默认为false
  * @param  option：上传进度回调函数，用于传递额外的配置选项, 默认为空对象
  * @return Promise：返回一个Promise对象，该对象在请求成功时解析为响应数据，在请求失败时拒绝为错误信息
  */
  upload(url, param, isAdmin = false, option) {
    let config;
    if (isAdmin) {
      config = {  // 从本地请求中拿出管理员token，将其添加到请求头中。设置Content-Type为multipart/form-data，表示上传的是文件或表单数据。
        headers: {"Authorization": localStorage.getItem("adminToken"), "Content-Type": "multipart/form-data"},
        timeout: 60000  // 设置请求超时时间为60秒
      };
    } else {
      config = {
        headers: {"Authorization": localStorage.getItem("userToken"), "Content-Type": "multipart/form-data"},
        timeout: 60000
      };
    }
    if (typeof option !== "undefined") {
      // 如果提供了option参数，并且option中包含onProgress方法，则设置一个上传进度回调函数
      config.onUploadProgress = progressEvent => {
        if (progressEvent.total > 0) {  // 如果总上传进度大于0
          progressEvent.percent = progressEvent.loaded / progressEvent.total * 100;  // 计算上传进度百分比
        }
        option.onProgress(progressEvent);  // 调用option中的onProgress方法，将上传进度传递给它
      };
    }

    return new Promise((resolve, reject) => {
      axios   // 使用axios.post方法发送POST请求，将url、param和config作为参数传递
        .post(url, param, config)
        .then(res => {
          resolve(res.data);  // 在请求成功时，将响应数据传递给resolve函数
        })
        .catch(err => {
          reject(err);       // 在请求失败时，将错误信息传递给reject函数
        });
    });
  },

  /**
  * @author DavidLee 
  * @title upload 
  * @date 2024-10-14
  * @description 将文件上传到七牛云存储
  * @param  url：请求的URL地址
  * @param  params：请求的参数，默认为空对象
  * @return Promise：返回一个Promise对象，该对象在请求成功时解析为响应数据，在请求失败时拒绝为错误信息
  */
  uploadQiniu(url, param) {
    let config = {
      headers: {"Content-Type": "multipart/form-data"},  // 设置请求头为multipart/form-data，表示上传的是文件
      timeout: 60000                                     // 设置请求超时时间为60秒
    };

    return new Promise((resolve, reject) => {
      axios
        .post(url, param, config)  // 使用axios.post方法发送POST请求，将url、param和config作为参数传递
        .then(res => {
          resolve(res.data);       // 在请求成功时，将响应数据传递给resolve函数
        })
        .catch(err => {
          reject(err);             // 在请求失败时，将错误信息传递给reject函数
        });
    });
  }
}
